Skip to content

feat: generate Android FirebaseMessagingService for Expo push notifications#385

Open
Rosie-Kennelly-1 wants to merge 1 commit intomainfrom
rosie/android-expo-push-kotlin-generation
Open

feat: generate Android FirebaseMessagingService for Expo push notifications#385
Rosie-Kennelly-1 wants to merge 1 commit intomainfrom
rosie/android-expo-push-kotlin-generation

Conversation

@Rosie-Kennelly-1
Copy link

@Rosie-Kennelly-1 Rosie-Kennelly-1 commented Mar 6, 2026

Why?

towards: https://github.com/intercom/intercom/issues/360467

The Expo config plugin automates iOS push notification setup (since PR #191) but has no Android equivalent. Expo developers' end users silently never receive push notifications on Android when a support agent replies — the only workaround is manually creating native Kotlin files, which defeats the purpose of using Expo.

How?

A new config plugin generates a Kotlin FirebaseMessagingService at expo prebuild time that forwards Intercom pushes to the SDK and passes non-Intercom messages through for other handlers. Also conditionally adds firebase-messaging to the app module's build.gradle (the native module declares it as implementation/private, so the app module needs its own copy).

Part 1 of 2 — manifest registration and plugin wiring follow in:

Related:

Generated with Claude Code

…ations

Adds an Expo config plugin that generates a Kotlin FirebaseMessagingService
at prebuild time. The service forwards FCM tokens and Intercom push messages
to the Intercom SDK, and passes non-Intercom messages through to other
handlers. Also conditionally adds the firebase-messaging gradle dependency
to the app module when not already present.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@liutingdu
Copy link
Member

Hey! I was reviewing this PR chain (#383, #385, #384) and wanted to flag a potential issue with how the generated FirebaseMessagingService interacts with expo-notifications.

The concern: Android only dispatches MESSAGING_EVENT to one service (highest priority wins). In PR #384, when an existing FCM service is detected (e.g. ExpoFirebaseMessagingService from expo-notifications), registration is skipped entirely with a warning to "route Intercom pushes manually" — but Expo users can't write native code, so this effectively means Intercom pushes remain broken for the most common Expo setup.

Priority conflict breakdown:

  • Generated IntercomFirebaseMessagingService: priority 10
  • ExpoFirebaseMessagingService: priority -1
  • Native IntercomFcmMessengerService (from intercom-sdk-fcm): priority -400

If we don't skip and do register at priority 10, Intercom pushes work but super.onMessageReceived() goes to the FirebaseMessagingService base class (no-op), so expo-notifications breaks.

Possible fix: conditionally extend ExpoFirebaseMessagingService instead of FirebaseMessagingService when expo-notifications is present, so super.onMessageReceived() falls through to Expo's handler. Something like:

// When expo-notifications is installed:
class IntercomFirebaseMessagingService : ExpoFirebaseMessagingService() {
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        if (IntercomModule.isIntercomPush(remoteMessage)) {
            IntercomModule.handleRemotePushMessage(application, remoteMessage)
        } else {
            super.onMessageReceived(remoteMessage) // → Expo handles it
        }
    }
}

The config plugin could detect expo-notifications in the project's dependencies at prebuild time and choose the right superclass.

This would cover the common case where an Expo app uses both expo-notifications and Intercom.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants